package com.nbufe.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nbufe.common.core.domain.R;
import com.nbufe.domain.ResponseResult;
import com.nbufe.domain.dto.QueryFixCarbonDTO;
import com.nbufe.domain.dto.QueryIndustryProduceDTO;
import com.nbufe.domain.entity.EmissionOrigin;
import com.nbufe.domain.entity.FixCarbon;
import com.nbufe.domain.entity.IndustoryProduce;
import com.nbufe.domain.entity.Material;
import com.nbufe.domain.entity.Process;
import com.nbufe.domain.form.AddIndustoryProduceForm;
import com.nbufe.domain.form.ModifyIndustoryProduceForm;
import com.nbufe.domain.form.QueryIndustryProduceForm;
import com.nbufe.domain.vo.PageVo;
import com.nbufe.domain.vo.industry.AddYearMonthSolventVo;
import com.nbufe.domain.vo.industry.YearMonthSolventCo2Vo;
import com.nbufe.mapper.EmissionOriginMapper;
import com.nbufe.mapper.MaterialMapper;
import com.nbufe.mapper.ProcessMapper;
import com.nbufe.service.DataService;
import com.nbufe.service.IndustoryProduceService;
import com.nbufe.utils.BeanCopyUtils;
import com.nbufe.utils.HttpContextUtils;
import com.nbufe.utils.UnderUtil;
import io.swagger.models.auth.In;
import org.springframework.stereotype.Service;
import com.nbufe.mapper.IndustoryProduceMapper;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * (IndustoryProduce)表服务实现类
 *
 * @author LZH
 * @since 2023-04-01 10:10:33
 */
@Service("industoryProduceService")
public class IndustoryProduceServiceImpl extends ServiceImpl<IndustoryProduceMapper, IndustoryProduce> implements IndustoryProduceService {

    @Resource
    private DataService dataService;

    @Resource
    private MaterialMapper materialMapper;

    @Resource
    private EmissionOriginMapper emissionOriginMapper;

    @Resource
    private ProcessMapper processMapper;

    @Override
    public R calTargetYearMonthSolventCo2(YearMonthSolventCo2Vo vo) {
        IndustoryProduce material = getTargetYearMonthSolventMaterial(vo);

        if (Objects.isNull(material)) {
            return R.ok(0);
        }

        BigDecimal emissionFactor = BigDecimal.valueOf(material.getEmissionFactor());
        BigDecimal consumption = BigDecimal.valueOf(material.getConsumption());

        double carbonEmission = emissionFactor.multiply(consumption).doubleValue();
        return R.ok(carbonEmission);
    }

    @Override
    public R addTargetYearMonthSolvent(AddYearMonthSolventVo vo) {
        BigDecimal consumption = BigDecimal.valueOf(vo.getConsumption());
        BigDecimal emissionFactor = BigDecimal.valueOf(vo.getEmissionFactor());
        double carbonEmission = consumption.multiply(emissionFactor).doubleValue();

        IndustoryProduce material = getById(vo.getMaterialId());
        //指定年月材料不存在
        if (Objects.isNull(material)) {
            IndustoryProduce industoryProduce = BeanCopyUtils.copyBean(vo, IndustoryProduce.class);
            industoryProduce.setCarbonEmission(carbonEmission);
            save(industoryProduce);
        } else {
            //存在
            double newConsumption = BigDecimal.valueOf(material.getConsumption())
                    .add(BigDecimal.valueOf(vo.getConsumption())).doubleValue();
            material.setConsumption(newConsumption);
            material.setCarbonEmission(material.getCarbonEmission() + carbonEmission);
            updateById(material);
        }
        return R.ok();
    }

    @Override
    public Double queryAllMaterialCarbonByMonth(Integer year, Integer month) {
        LambdaQueryWrapper<IndustoryProduce> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IndustoryProduce::getYear, year);
        queryWrapper.eq(IndustoryProduce::getMonth, month);
        List<IndustoryProduce> industoryProduceList = list(queryWrapper);
        return industoryProduceList
                .stream()
                .mapToDouble(IndustoryProduce::getCarbonEmission).sum();
    }

    @Override
    public Double queryAllMaterialCarbonByYear(Integer year) {
        LambdaQueryWrapper<IndustoryProduce> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IndustoryProduce::getYear, year);
        List<IndustoryProduce> industoryProduceList = list(queryWrapper);
        return industoryProduceList.stream()
                .mapToDouble(IndustoryProduce::getCarbonEmission).sum();
    }

    @Override
    public Double queryTargetYearMaterialCo2(Integer materialId, Integer year) {
        LambdaQueryWrapper<IndustoryProduce> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IndustoryProduce::getMaterialId, materialId);
        queryWrapper.eq(IndustoryProduce::getYear, year);
        return list(queryWrapper).stream()
                .mapToDouble(IndustoryProduce::getCarbonEmission).sum();
    }

    @Override
    public ResponseResult pageList(QueryIndustryProduceForm form) {
        Page<IndustoryProduce> page = new Page<>(form.getPageNum(), form.getPageSize());
        QueryWrapper<IndustoryProduce> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Objects.nonNull(form.getMaterialId()), "material_id", form.getMaterialId());
        queryWrapper.eq(Objects.nonNull(form.getYear()), "year", form.getYear());
        queryWrapper.eq(Objects.nonNull(form.getMonth()), "month", form.getMonth());

        String tenantId = HttpContextUtils.getRequest().getHeader("tenant-id");
        queryWrapper.eq("tenant_id", Long.valueOf(tenantId));

        List<Map<String, String>> sortArr = form.getSortArr();
        if (sortArr.size() > 0) {
            for (Map<String, String> map : sortArr) {
                String order = map.get("order");
                String prop = map.get("prop");
                prop = UnderUtil.camel2under(prop);
                if ("ascending".equals(order)) {
                    queryWrapper.orderByAsc(prop);
                } else if ("descending".equals(order)) {
                    queryWrapper.orderByDesc(prop);
                }
            }
        }

        page(page, queryWrapper);

        List<EmissionOrigin> emissionOriginList = dataService.queryTargetStageEmissionOrigin(2);

        List<IndustoryProduce> fixCarbonList = page.getRecords();
        List<QueryIndustryProduceDTO> queryIndustryProduceDto = BeanCopyUtils.copyBeanList(fixCarbonList, QueryIndustryProduceDTO.class);
        //封装电力热力名称
        queryIndustryProduceDto = queryIndustryProduceDto.stream()
                .peek(dto -> {
                    Process process = processMapper.selectById(dto.getProcessId());
                    dto.setProcessName(process != null ? process.getName() : "");
                    for (EmissionOrigin emissionOrigin : emissionOriginList) {
                        if (emissionOrigin.getId().equals(dto.getMaterialId())) {
                            dto.setName(emissionOrigin.getName());
                            break;
                        }
                    }
                }).collect(Collectors.toList());

        PageVo pageVo = new PageVo(page.getTotal(), queryIndustryProduceDto);
        return ResponseResult.okResult(pageVo);
    }

    @Override
    public ResponseResult listAllIndustryProduceMaterial() {
        List<Material> materialList = materialMapper.selectList(new LambdaQueryWrapper<Material>().eq(Material::getProduceStage, 2));
        return ResponseResult.okResult(materialList);
    }

    @Override
    public List<Integer> listYears() {
        return baseMapper.selectAllYears();
    }

    @Override
    public ResponseResult deleteOneOrBatch(List<Integer> ids) {
        if (ids.size() > 0) {
            removeBatchByIds(ids);
        }
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult addIndustoryProduce(AddIndustoryProduceForm form) {
        IndustoryProduce industoryProduce = BeanCopyUtils.copyBean(form, IndustoryProduce.class);
        industoryProduce.setCarbonEmission(
                BigDecimal.valueOf(form.getConsumption()).multiply(BigDecimal.valueOf(form.getEmissionFactor()))
                        .setScale(2, RoundingMode.UP).doubleValue()
        );
        save(industoryProduce);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult modifyIndustoryProduceInfo(ModifyIndustoryProduceForm form) {
        IndustoryProduce industoryProduce = BeanCopyUtils.copyBean(form, IndustoryProduce.class);
        industoryProduce.setCarbonEmission(
                BigDecimal.valueOf(form.getConsumption()).multiply(BigDecimal.valueOf(form.getEmissionFactor()))
                        .setScale(2, RoundingMode.UP).doubleValue()
        );
        updateById(industoryProduce);
        return ResponseResult.okResult();
    }

    private IndustoryProduce getTargetYearMonthSolventMaterial(YearMonthSolventCo2Vo vo) {
        LambdaQueryWrapper<IndustoryProduce> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IndustoryProduce::getYear, vo.getYear());
        queryWrapper.eq(IndustoryProduce::getMonth, vo.getMonth());
        queryWrapper.eq(IndustoryProduce::getMaterialId, vo.getMaterialId());

        return getOne(queryWrapper);
    }
}

